package cn.shyouchi.wuguanjia.android.utils;


import android.text.TextUtils;
import android.util.Base64;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;


/**
 * 加解密工具
 */
public final class EncryptUtil {


    boolean debug = true;
    private final static String ENCRYPT_KEY = "Ysu8bzvM9Xra9zdq/z0mKQ==";
    private final static String DEFAULT_KEY = "!%$#*&@[";

    private static String sTemp = "";

    /**
     * 使用<code>secret</code>对paramValues按以下算法进行加密： <br/>
     *
     * @param paramValues 参数列表
     * @return 加密字符串
     */
    public static String encrypt(Map<String, String> paramValues) {
        return new String(encrypt(paramValues, null));
    }

    public static Map<String, String> encryptWithMap(Map<String, String> paramValues) {
        Map<String, String> par = new HashMap<>();
        par.put("data", new String(encrypt(paramValues, null)));
        return par;
    }


    /**
     * 使用<code>secret</code>对文本按以下算法进行加密： <br/>
     *
     * @param text 文本
     * @return 加密字符串
     */
    public static String encrypt(String text) {
        String result = "";
        try {
            result = new String(encode(text)).replace("\n", "");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    /**
     * 对paramValues进行加密，忽略其中ignoreParamNames
     *
     * @param paramValues      参数列表
     * @param ignoreParamNames 忽略列表
     * @return 加密字节数组
     */
    public static byte[] encrypt(Map<String, String> paramValues,
                                 List<String> ignoreParamNames) {
        byte[] result = null;
        try {
            StringBuilder sb = new StringBuilder("{");
            ArrayList<String> paramNames = new ArrayList<>(paramValues.size());
            paramNames.addAll(paramValues.keySet());
            if (ignoreParamNames != null && !ignoreParamNames.isEmpty()) {
                for (String ignoreParamName : ignoreParamNames) {
                    paramNames.remove(ignoreParamName);
                }
            }
            Collections.sort(paramNames);

            for (String paramName : paramNames) {
                sb.append("\"").append(paramName).append("\":");
                sb.append("\"").append(paramValues.get(paramName)).append("\",");
            }
            sb.deleteCharAt(sb.lastIndexOf(","));
            sb.append("}");

            result = encode(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 对文本进行加密
     *
     * @param data 文本
     * @return 加密字节数组
     */
    private static byte[] encode(String data) {
        if (TextUtils.isEmpty(sTemp)) {
            sTemp = getEncryptKey();
        }

        data = convertToUnicode(data);
        int secretLength = sTemp.length();
        int length = data.length();
        StringBuilder val = new StringBuilder();
        for (int i = 0; i < length; i++) {
            val.append((char) (data.charAt(i) ^ sTemp.charAt(i % secretLength)));
        }

        return Base64.encode(val.toString().getBytes(), Base64.DEFAULT);
    }

    public static String deEncrypt(String data) {

        if (TextUtils.isEmpty(data)) {
            return "";
        }
        if (TextUtils.isEmpty(sTemp)) {
            sTemp = getEncryptKey();
        }
        int secretLength = sTemp.length();
        StringBuilder val = new StringBuilder();
        String temp = new String(Base64.decode(data, Base64.DEFAULT));
        int length = temp.length();
        for (int i = 0; i < length; i++) {
            val.append((char) (temp.charAt(i) ^ sTemp.charAt(i % secretLength)));
        }

//        Logger.e(data + "\n" + val.toString());
        return val.toString();
    }

    private static String convertToUnicode(String text) {
        StringBuilder result = new StringBuilder();
        int length = text.length();
        for (int i = 0; i < length; i++) {
            char c = text.charAt(i);
            if (c >= 19968 && c <= 171941) {//汉字范围 \u4e00-\u9fa5 (中文)
                result.append("\\u").append(Integer.toHexString(c));
            } else {
                result.append(c);
            }
        }

        return result.toString();
    }

    private static String getEncryptKey() {
        String key = "";
        try {
            DESKeySpec desKey = new DESKeySpec(DEFAULT_KEY.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secureKey = keyFactory.generateSecret(desKey);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, secureKey, new SecureRandom());
            key = new String(cipher.doFinal(Base64.decode(ENCRYPT_KEY, Base64.DEFAULT)));
        } catch (Exception ignored) {
        }

        return key;
    }
}
